package gui.customizer.panes.interfaces;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.SSHConnectionProxy;
import net.miginfocom.swing.MigLayout;
import net.schmizz.sshj.connection.channel.direct.Session.Command;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import core.models.NetInterface;
import core.models.NetInterfaces;

public class Configuration extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = -5004510124154547447L;
	private JList listInterfaces;
	private JPanel editPanel;
	private Logger logger;

	// Editor fields
	private JLabel lblName;
	private JLabel lblType;
	private JLabel lblAuto;
	private JTextField txtName;
	private JComboBox cmbType;
	private JCheckBox chckbxAuto;
	private JLabel lblAddress;
	private JTextField txtAddress;
	private JLabel lblNetmask;
	private JTextField txtNetmask;
	private JLabel lblGateway;
	private JLabel lblBroadcast;
	private JLabel lblNetwork;
	private JTextField txtGateway;
	private JTextField txtBroadcast;
	private JTextField txtNetwork;
	private JButton btnGateway;
	private JButton btnBroadcast;
	private JButton btnNetwork;
	private Boolean gatewayFieldsState;
	private Boolean broadcastFieldsState;
	private Boolean networkFieldsState;
	private JComboBox cmbLists;

	private JList listUpsDows;
	private JButton btnAddStringElement;
	private JButton btnDeleteStringElement;
	private JButton btnEditStringElement;

	private DefaultListModel upsModel;
	private DefaultListModel downsModel;
	private DefaultListModel preDownsModel;
	private DefaultListModel preUpsModel;
	private JButton btnSaveIface;

	public Configuration() {
		setLayout(new MigLayout("", "[100px:300px][][grow]", "[][][grow]"));
		logger = LoggerFactory.getLogger(Configuration.class);
		// Loading interfaces (here or in interfaces.java)
		final NetInterfaces interfaces = new NetInterfaces();
		final SSHConnectionProxy conn = new SSHConnectionProxy();
		try {
			File interfacesFile = conn.downloadInterfaces();
			interfaces.loadInterfaces(interfacesFile);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			// TODO Maybe some error dialog
			e.printStackTrace();
			return;
		}

		listInterfaces = new JList(interfaces);
		listInterfaces.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		listInterfaces.setLayoutOrientation(JList.VERTICAL);
		listInterfaces.addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting())
					return;
				drawEditFields(editPanel,
						(NetInterface) listInterfaces.getSelectedValue());
			}
		});

		JScrollPane listScroller = new JScrollPane(listInterfaces);
		add(listScroller, "cell 0 0 1 2,growx,aligny top");

		JButton btnAdd = new JButton("Add");
		btnAdd.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final JDialog dialog = new JDialog();
				final JTextField txtNewInterfaceName = new JTextField();
				final JButton btnSave = new JButton("Save");
				btnSave.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						if (txtNewInterfaceName.equals("")) {
							Toolkit.getDefaultToolkit().beep();
							txtNewInterfaceName.requestFocusInWindow();
							return;
						}
						NetInterface iface = new NetInterface();
						iface.setName(txtNewInterfaceName.getText());
						iface.setAuto(false);
						iface.setType("dhcp");
						interfaces.addElement(iface);
						
						dialog.setVisible(false);
						dialog.dispose();
					}
				});
				dialog.getContentPane().setLayout(new MigLayout("", "[150px:n,grow]", "[][]"));
				dialog.getContentPane().add(txtNewInterfaceName, "cell 0 0,growx");
				dialog.getContentPane().add(btnSave, "cell 0 1,alignx center");
				
				dialog.setLocationRelativeTo(getRootPane());
				dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
				dialog.pack();
				dialog.setVisible(true);
			}
		});
		add(btnAdd, "cell 1 0,growx");

		JButton btnDelete = new JButton("Delete");
		btnDelete.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final int index = listInterfaces.getSelectedIndex();
				if (index != -1) {
					interfaces.remove(index);
				}
			}
		});
		add(btnDelete, "cell 1 1,growx,aligny top");
		
		JButton btnSaveAndSend = new JButton("Save and send");
		btnSaveAndSend.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				try {
					File result = interfaces.generateInterfacesFile();
					logger.info("file {} generated", result.getName());
					conn.sendInterfaces(result);
				} catch (IOException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
			}
		});
		add(btnSaveAndSend, "cell 2 0");

		editPanel = new JPanel();
		editPanel.setLayout(new MigLayout("",
				"[50px:70px][60px:100px][]20[100px:250.00px][]",
				"[][]15[][][][][]"));

		JScrollPane editPanelScroller = new JScrollPane(editPanel);

		editPanelScroller.setBorder(BorderFactory.createTitledBorder("Edit"));
		add(editPanelScroller, "cell 0 2 3 1,grow");
		
		// Fields initialization
		btnSaveIface = new JButton("Save changes");
		btnSaveIface.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				NetInterface iface = new NetInterface();
				iface.setAuto(chckbxAuto.isSelected());
				iface.setName(txtName.getText());
				iface.setType((String)cmbType.getSelectedItem());
				if (iface.getType().equals("static")) {
					iface.setAddress(txtAddress.getText());
					iface.setNetmask(txtNetmask.getText());
					if (txtGateway.isEnabled()) iface.setGateway(txtGateway.getText());
					if (txtBroadcast.isEnabled()) iface.setBroadcast(txtBroadcast.getText());
					if (txtNetwork.isEnabled()) iface.setNetwork(txtNetwork.getText());
				}
				iface.setUpListUsingModel(upsModel);
				iface.setDownListUsingModel(downsModel);
				iface.setPreUpListUsingModel(preUpsModel);
				iface.setPreDownListUsingModel(preDownsModel);
				
				if (iface.isValid()) {
					final int index = listInterfaces.getSelectedIndex();
					interfaces.remove(index);
					interfaces.add(index, iface);
				}
				else {
					Toolkit.getDefaultToolkit().beep();
					logger.warn("Interface {} is not valid", iface.getName());
				}
			}
		});
		lblName = new JLabel("Name");
		txtName = new JTextField();
		
		lblType = new JLabel("Type");
		cmbType = new JComboBox();
		
		lblAuto = new JLabel("Auto");
		chckbxAuto = new JCheckBox();
		
		listUpsDows = new JList();
		
		btnAddStringElement = new JButton("Add");
		btnAddStringElement.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final DefaultListModel model = (DefaultListModel) listUpsDows.getModel();
				if (model == null) 
					return;
				final JDialog dialog = new JDialog();
				final JTextField txtNewValue = new JTextField();
				final JButton btnSave = new JButton("Save");
				btnSave.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent arg0) {
						if (!txtNewValue.equals("")) {
							model.addElement(txtNewValue.getText());
						}
						dialog.setVisible(false);
						dialog.dispose();
					}
				});
				
				dialog.getContentPane().setLayout(new MigLayout("", "[150px:n,grow]", "[][]"));
				dialog.getContentPane().add(txtNewValue, "cell 0 0,growx");
				dialog.getContentPane().add(btnSave, "cell 0 1,alignx center");
				
				dialog.setLocationRelativeTo(getRootPane());
				dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
				dialog.pack();
				dialog.setVisible(true);
			}
		});
		btnDeleteStringElement = new JButton("Delete");
		btnDeleteStringElement.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final int index = listUpsDows.getSelectedIndex();
				final DefaultListModel model = (DefaultListModel) listUpsDows.getModel();
				if (model == null || index == -1)
					return;
				model.remove(index);
			}
		});
		btnEditStringElement = new JButton("Edit");
		btnEditStringElement.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final int index = listUpsDows.getSelectedIndex();
				final DefaultListModel model = (DefaultListModel) listUpsDows
						.getModel();
				if (model == null)
					return;
				final JDialog dialog = new JDialog();
				final JTextField txtNewValue = new JTextField((String)model.getElementAt(index));
				final JButton btnSave = new JButton("Save");
				btnSave.addActionListener(new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						if (!txtNewValue.equals("")) {
							model.removeElementAt(index);
							model.add(index, txtNewValue.getText());
						}
						dialog.setVisible(false);
						dialog.dispose();
					}
				});
				dialog.getContentPane().setLayout(new MigLayout("", "[150px:n,grow]", "[][]"));
				dialog.getContentPane().add(txtNewValue, "cell 0 0,growx");
				dialog.getContentPane().add(btnSave, "cell 0 1,alignx center");

				dialog.setLocationRelativeTo(getRootPane());
				dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
				dialog.pack();
				dialog.setVisible(true);
			}
		});
		
		// Fields for static type
		lblAddress = new JLabel("Address");
		txtAddress = new JTextField();
		
		lblNetmask = new JLabel("Netmask");
		txtNetmask = new JTextField();
		
		lblGateway = new JLabel("Gateway");
		txtGateway = new JTextField();
		btnGateway = new JButton();
		btnGateway.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				gatewayFieldsState = !gatewayFieldsState;
				setBtnAndTxtState(btnGateway, txtGateway, gatewayFieldsState);
			}
		});
		
		lblBroadcast = new JLabel("Broadcast");
		txtBroadcast = new JTextField();
		btnBroadcast = new JButton();
		btnBroadcast.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				broadcastFieldsState = !broadcastFieldsState;
				setBtnAndTxtState(btnBroadcast, txtBroadcast,
						broadcastFieldsState);
			}
		});

		lblNetwork = new JLabel("Network");
		txtNetwork = new JTextField();
		btnNetwork = new JButton();
		btnNetwork.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				networkFieldsState = !networkFieldsState;
				setBtnAndTxtState(btnNetwork, txtNetwork, networkFieldsState);
			}
		});
		
		// Ups, Downs, PreUps, PreDowns combo
		cmbLists = new JComboBox(NetInterface.getListsDirectives());
		cmbLists.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (e.getStateChange() == ItemEvent.SELECTED) {
					String item = (String) cmbLists.getSelectedItem();
					if (item.equals("up")) {
						listUpsDows.setModel(upsModel);
					} else if (item.equals("down")) {
						listUpsDows.setModel(downsModel);
					} else if (item.equals("pre-up")) {
						listUpsDows.setModel(preUpsModel);
					} else if (item.equals("pre-down")) {
						listUpsDows.setModel(preDownsModel);
					}
				}
			}
		});

	}

	private void drawEditFields(final JPanel panel, final NetInterface iface) {
		panel.removeAll();
		if (iface == null) {
			updateUI();
			return;
		}
		
		// Save button
		editPanel.add(btnSaveIface, "cell 4 0,alignx right");
	
		// Name
		editPanel.add(lblName, "cell 0 0");
		txtName.setText(iface.getName());
		editPanel.add(txtName, "cell 0 1,growx");
		txtName.setColumns(10);

		// Type
		editPanel.add(lblType, "cell 1 0");
		cmbType = new JComboBox(iface.getPossibleTypes());
		cmbType.setSelectedItem(iface.getType());
		cmbType.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent arg0) {
				if (arg0.getStateChange() == ItemEvent.SELECTED) {
					iface.setType((String) cmbType.getSelectedItem());
					drawEditFields(panel, iface);
				}	
			}
		});
		editPanel.add(cmbType, "cell 1 1,growx");

		// Auto
		editPanel.add(lblAuto, "cell 2 0,alignx right");
		chckbxAuto.setSelected(iface.isAuto());
		editPanel.add(chckbxAuto, "cell 2 1,alignx right");

		// Ups, Downs, PreUps, PreDowns lists models
		upsModel = iface.getUpsModel();
		downsModel = iface.getDownsModel();
		preUpsModel = iface.getPreUpsModel();
		preDownsModel = iface.getPreDownsModel();

		// Ups, Downs, PreUps, PreDowns lists
		listUpsDows.setModel(upsModel);

		if (iface.getType().equals("static"))
			drawStaticTypeFields(iface);
		else
			drawOnlyDirectivesLists(iface);
		updateUI();
	}

	private void drawStaticTypeFields(final NetInterface iface) {
		// Address
		editPanel.add(lblAddress, "cell 0 2,alignx trailing");
		txtAddress.setText(iface.getAddress());
		editPanel.add(txtAddress, "cell 1 2 2 1,growx");
		txtAddress.setColumns(10);

		// Netmask
		editPanel.add(lblNetmask, "cell 0 3,alignx trailing");
		txtNetmask.setText(iface.getNetmask());
		editPanel.add(txtNetmask, "cell 1 3 2 1,growx");
		txtNetmask.setColumns(10);

		// Gateway
		editPanel.add(lblGateway, "cell 0 4,alignx trailing");
		editPanel.add(txtGateway, "cell 1 4,growx");
		txtGateway.setColumns(10);
		editPanel.add(btnGateway, "cell 2 4,growx");
		gatewayFieldsState = iface.getGateway() == null ? Boolean.FALSE
				: Boolean.TRUE;
		setBtnAndTxtState(btnGateway, txtGateway, gatewayFieldsState);
		if (gatewayFieldsState.equals(Boolean.TRUE))
			txtGateway.setText(iface.getGateway());

		// Broadcast
		editPanel.add(lblBroadcast, "cell 0 5,alignx trailing");
		editPanel.add(txtBroadcast, "cell 1 5,growx");
		txtBroadcast.setColumns(10);
		editPanel.add(btnBroadcast, "cell 2 5,growx");
		broadcastFieldsState = iface.getBroadcast() == null ? Boolean.FALSE
				: Boolean.TRUE;
		setBtnAndTxtState(btnBroadcast, txtBroadcast, broadcastFieldsState);
		if (broadcastFieldsState.equals(Boolean.TRUE))
			txtBroadcast.setText(iface.getBroadcast());

		// Network
		editPanel.add(lblNetwork, "cell 0 6,alignx trailing");
		editPanel.add(txtNetwork, "cell 1 6,growx");
		txtNetwork.setColumns(10);
		editPanel.add(btnNetwork, "cell 2 6,growx");
		networkFieldsState = iface.getNetwork() == null ? Boolean.FALSE
				: Boolean.TRUE;
		setBtnAndTxtState(btnNetwork, txtNetwork, networkFieldsState);
		if (networkFieldsState.equals(Boolean.TRUE))
			txtNetwork.setText(iface.getNetwork());

		// Elements for edit ups/downs list
		editPanel.add(cmbLists, "cell 3 2,alignx left");
		editPanel.add(listUpsDows, "cell 3 3 1 4,grow");
		editPanel.add(btnAddStringElement, "cell 4 3,w 70!");
		editPanel.add(btnDeleteStringElement, "cell 4 4,w 70!");
		editPanel.add(btnEditStringElement, "cell 4 5,w 70!");
	}
	
	private void setBtnAndTxtState(JButton button, JTextField txt, Boolean state) {
		txt.setText("");
		txt.setEnabled(state);
		button.setText(state ? "-" : "+");
	}

	private void drawOnlyDirectivesLists(NetInterface iface) {
		editPanel.add(cmbLists, "cell 0 2,growx");
		editPanel.add(listUpsDows, "cell 0 3 3 4,grow");
		editPanel.add(btnAddStringElement, "cell 3 4,w 70!");
		editPanel.add(btnDeleteStringElement, "cell 3 5,w 70!");
		editPanel.add(btnEditStringElement, "cell 3 6,w 70!");
	}	
}
